//
//  String+Extension.swift
//  8btc
//
//  Created by Steven Xie on 2018/11/15.
//  Copyright © 2018 Hangzhou Shichuo Information Technology Co, Ltd. All rights reserved.
//

import YYText

public extension String {
    static func popEnterFromHeaderAndFooter(_ origin: String) -> String {
        var tmp = origin
        while tmp.first == "\n" {
            _ = tmp.removeFirst()
        }

        while tmp.last == "\n" {
            _ = tmp.popLast()
        }
        return tmp
    }

    func tryTranslateHTML() -> NSAttributedString? {
        let stylecss = """
        <style>body {line-height: 20px; letter-spacing:0.8px; font-size: 16px;color: #000A12;text-align: justify;font-family: PingFangSC-Regular;padding: 2;}
        img {max-width:100% !important;height:auto !important;}
        p {padding: 0;margin: 0 0 0px 0; word-wrap: break-word;}
        </style>
        """
        let htmlBr = replacingOccurrences(of: "\n", with: "<br>")
        let meta = stylecss + htmlBr
        let attrDoc = [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html.rawValue]

        var attributedString: NSAttributedString?
        if let anEncoding = meta.data(using: String.Encoding(rawValue: String.Encoding.unicode.rawValue)) {
            
            
            attributedString = try? NSAttributedString(data: anEncoding,
                                                       options: attrDoc,
                                                       documentAttributes: nil)
            if let atString = attributedString{
                let style = NSMutableParagraphStyle()
                style.minimumLineHeight = 20
                style.lineBreakMode = .byCharWrapping
                
                let mutableArrString = NSMutableAttributedString(attributedString: atString)
                mutableArrString.addAttributes([NSAttributedString.Key.paragraphStyle : style,
                                                NSAttributedString.Key.kern: 0.8],
                                               range: NSRange(location: 0, length: mutableArrString.length))
                attributedString = mutableArrString
            }
        }
        return attributedString
    }

    // 将原始的url编码为合法的url
    func urlEncoded() -> String {
        let encodeUrlString = addingPercentEncoding(withAllowedCharacters:
            .urlQueryAllowed)
        return encodeUrlString ?? ""
    }

    // 将编码后的url转换回原始的url
    func urlDecoded() -> String {
        return removingPercentEncoding ?? ""
    }

    // MARK: - String Reg

    func matchesForRegexInText(regex: String) -> [String] {
        do {
            let regex = try NSRegularExpression(pattern: regex, options: [])
            let nsString = self as NSString
            let results = regex.matches(in: self, options: [], range: NSMakeRange(0, nsString.length))
            return results.map { nsString.substring(with: $0.range) }
        } catch let error as NSError {
            debugPrint("invalid regex: \(error.localizedDescription)")
            return []
        }
    }

    // MARK: - Version Compare

    private func compare(toVersion targetVersion: String) -> ComparisonResult {
        let versionDelimiter = "."
        var result: ComparisonResult = .orderedSame
        var versionComponents = components(separatedBy: versionDelimiter)
        var targetComponents = targetVersion.components(separatedBy: versionDelimiter)
        let spareCount = versionComponents.count - targetComponents.count

        if spareCount == 0 {
            result = compare(targetVersion, options: .numeric)
        } else {
            let spareZeros = repeatElement("0", count: abs(spareCount))
            if spareCount > 0 {
                targetComponents.append(contentsOf: spareZeros)
            } else {
                versionComponents.append(contentsOf: spareZeros)
            }
            result = versionComponents.joined(separator: versionDelimiter)
                .compare(targetComponents.joined(separator: versionDelimiter), options: .numeric)
        }
        return result
    }

    func isVersion(equalTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedSame }
    func isVersion(greaterThan targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedDescending }
    func isVersion(greaterThanOrEqualTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) != .orderedAscending }
    func isVersion(lessThan targetVersion: String) -> Bool { return compare(toVersion: targetVersion) == .orderedAscending }
    func isVersion(lessThanOrEqualTo targetVersion: String) -> Bool { return compare(toVersion: targetVersion) != .orderedDescending }

    // 根据开始位置和长度截取字符串
    func subString(start: Int, length: Int = -1) -> String {
        var len = length
        if len == -1 {
            len = count - start
        }
        let st = index(startIndex, offsetBy: start)
        let en = index(st, offsetBy: len)
        return String(self[st ..< en])
    }

}

public extension String {
    
    /// range转换为NSRange
    func nsRange(from range: Range<String.Index>) -> NSRange {
        return NSRange(range, in: self)
    }
    
    /// NSRange转化为range
    func range(from nsRange: NSRange) -> Range<String.Index>? {
        guard
            let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex),
            let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex),
            let from = String.Index(from16, within: self),
            let to = String.Index(to16, within: self)
        else { return nil }
        return from ..< to
    }
}

public extension String {
    /// （如果backwards参数设置为true，则返回最后出现的位置）
    func positionOf(sub: String, backwards: Bool = false) -> Int {
        // 如果没有找到就返回-1
        var pos = -1
        if let range = range(of: sub, options: backwards ? .backwards : .literal) {
            if !range.isEmpty {
                pos = distance(from: startIndex, to: range.lowerBound)
            }
        }
        return pos
    }
}

public extension String {
    func textHeightCalculation(maxWidth: CGFloat, lineSpacing: CGFloat, font: UIFont) -> (CGFloat) {
        let attributedStr = NSMutableAttributedString(string: self)
        attributedStr.yy_font = font
        attributedStr.yy_lineSpacing = lineSpacing
        let layout = YYTextLayout(containerSize: CGSize(width: maxWidth, height: CGFloat(MAXFLOAT)), text: attributedStr)!
        return layout.textBoundingSize.height
    }
}

public extension String {
     mutating func transToPinYin() -> String {
        let s = NSMutableString(string: self)
        CFStringTransform(s, nil, kCFStringTransformToLatin, false)
        CFStringTransform(s, nil, kCFStringTransformStripDiacritics, false)
        
        let pinyinArray = s.components(separatedBy: " ")
        var allString = ""
        var count: Int = 0
        for _ in 0..<pinyinArray.count {
            for a in 0..<pinyinArray.count {
                if a == count {
                    allString.append("#")
                }
                allString.append(pinyinArray[a])
            }
            allString.append(",")
            count += 1
        }
        
        var initialStr = ""
        for value in pinyinArray {
            if let chart = value.first {
                initialStr.append(chart)
            }
        }
        allString.append(initialStr)
        allString.append(self)
        return allString
    }
}

public extension String {
    init?(gbkData: Data) {
        //获取GBK编码, 使用GB18030是因为它向下兼容GBK
        let cfEncoding = CFStringEncodings.GB_18030_2000
        let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(cfEncoding.rawValue))
        //从GBK编码的Data里初始化NSString, 返回的NSString是UTF-16编码
        if let str = NSString(data: gbkData, encoding: encoding) {
            self = str as String
        } else {
            return nil
        }
    }
    
    var gbkData: Data {
        let cfEncoding = CFStringEncodings.GB_18030_2000
        let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(cfEncoding.rawValue))
        let gbkData = (self as NSString).data(using: encoding)!
        return gbkData
    }
    
}

public extension String {
    func clearEnter() -> String {
        var cont = replacingOccurrences(of: "<br>", with: "\n")
        cont = cont.replacingOccurrences(of: "&nbsp;", with: "\n")
        cont = cont.replacingOccurrences(of: "\r\n", with: "\n")
        cont = cont.replacingOccurrences(of: "\n\r", with: "\n")
        cont = cont.replacingOccurrences(of: " \n", with: "\n")
        cont = cont.replacingOccurrences(of: "\n ", with: "\n")
        cont = cont.replacingOccurrences(of: "<div>", with: "")
        cont = cont.replacingOccurrences(of: "</div>", with: "")
        while cont.contains("\n\n") {
            cont = cont.replacingOccurrences(of: "\n\n", with: "\n")
        }
        while cont.hasSuffix("\n"), cont.count > 2 {
            let range = cont.index(cont.endIndex, offsetBy: -1) ..< cont.endIndex
            cont.removeSubrange(range)
        }
        return cont
    }
}
